package common

import (
	"go.mongodb.org/mongo-driver/bson"
	"gopkg.in/mgo.v2"
	"strings"
)

type PageInfo struct {
	PageNum  int         `json:"pageNum"`
	PageSize int         `json:"pageSize"`
	Data     interface{} `json:"data"`
	Total    int         `json:"total"`
}

type TkMongo struct {
	Session *mgo.Session
	Coll    *mgo.Collection
}

func (tkm *TkMongo) GetDB(session *mgo.Session, dbname, coll string) {
	tkm.Session = session
	tkm.Coll = tkm.Session.DB(dbname).C(coll)
}

// 设置数据表索引
func (tkm *TkMongo) ExecQueryOneInSession(m []mgo.Index) {
	for _, index := range m {
		tkm.Coll.EnsureIndex(index)
	}
}

func (tkm *TkMongo) RemoveId(id interface{}) {
	tkm.Coll.RemoveId(id)
}
func (tkm *TkMongo) Remove(filter interface{}) {
	tkm.Coll.Remove(filter)
}
func (tkm *TkMongo) RemoveAll(filter interface{}) {
	tkm.Coll.RemoveAll(filter)
}

// 删除表
func (tkm *TkMongo) DropCollection() error {
	return tkm.Coll.DropCollection()
}
func (tkm *TkMongo) Insert(m interface{}) error {
	err := tkm.Coll.Insert(m)
	if err != nil {
		return err
	}
	//fmt.Println(insertResult.InsertedID)
	return nil
}
func (tkm *TkMongo) Set(filter interface{}, update interface{}) error {
	tupdate := bson.M{
		"$set": update,
	}
	err := tkm.Coll.Update(filter, tupdate)
	return err
}
func (tkm *TkMongo) SetId(id, update interface{}) error {
	tupdate := bson.M{
		"$set": update,
	}
	err := tkm.Coll.UpdateId(id, tupdate)
	return err
}
func (tkm *TkMongo) SetAll(filter, update interface{}) error {
	_, err := tkm.Coll.UpdateAll(filter, update)
	return err
}
func (tkm *TkMongo) Update(filter, update interface{}) error {
	err := tkm.Coll.Update(filter, update)
	return err
}
func (tkm *TkMongo) Upsert(filter, update interface{}) error {
	_, err := tkm.Coll.Upsert(filter, update)
	return err
}
func (tkm *TkMongo) All(filter, result interface{}) error {
	err := tkm.Coll.Find(filter).All(result)
	if err != nil {
		if err == mgo.ErrNotFound {
			return nil
		}
		return err
	}
	return nil
}
func (tkm *TkMongo) ListAll(filter interface{}, filds string, sort string, result interface{}) error {
	cursor := tkm.Coll.Find(filter)
	if filds != "" {
		fild := bson.M{}
		fildarr := strings.Split(filds, ",")
		for _, i := range fildarr {
			fild[i] = 1
		}
		cursor.Select(fild)
	}
	if sort != "" {
		cursor.Sort(sort)
	}
	err := cursor.All(result)
	if err != nil {
		if err == mgo.ErrNotFound {
			return nil
		}
		return err
	}
	return nil
}
func (tkm *TkMongo) FindOne(filter, result interface{}) error {
	err := tkm.Coll.Find(filter).One(result)
	//if err == mgo.ErrNotFound {
	//	result = nil
	//	return nil
	//}
	return err
}
func (tkm *TkMongo) Count(filter interface{}) (int, error) {
	return tkm.Coll.Find(filter).Count()
}
func (tkm *TkMongo) FindPageInfo(filter interface{}, filds string, pagesize, page int, sort string, result interface{}) (*PageInfo, error) {
	cursor := tkm.Coll.Find(filter)
	if filds != "" {
		fild := bson.M{}
		fildarr := strings.Split(filds, ",")
		for _, i := range fildarr {
			fild[i] = 1
		}
		cursor.Select(fild)
	}
	if sort != "" {
		cursor.Sort(sort)
	}
	//获取总条数
	count, err := cursor.Count()
	skip := (page - 1) * pagesize
	cursor.Skip(skip)
	cursor.Limit(pagesize)
	cursor.All(result)
	return &PageInfo{
		PageNum:  page,
		PageSize: pagesize,
		Total:    count,
		Data:     result,
	}, err
}

func (tkm *TkMongo) FindWithSort(filter interface{}, filds string, sort string, result interface{}) error {

	cursor := tkm.Coll.Find(filter)
	if filds != "" {
		fild := bson.M{}
		fildarr := strings.Split(filds, ",")
		for _, i := range fildarr {
			fild[i] = 1
		}
		cursor.Select(fild)
	}
	if sort != "" {
		cursor.Sort(sort)
	}
	err := cursor.All(result)
	if err != nil {
		if err == mgo.ErrNotFound {
			return nil
		}
		return err
	}
	return nil
}

func (tkm *TkMongo) FindOneWithSort(filter interface{}, filds string, sort string, result interface{}) error {
	cursor := tkm.Coll.Find(filter)
	if filds != "" {
		fild := bson.M{}
		fildarr := strings.Split(filds, ",")
		for _, i := range fildarr {
			fild[i] = 1
		}
		cursor.Select(fild)
	}
	if sort != "" {
		cursor.Sort(sort)
	}
	err := cursor.One(result)
	if err == mgo.ErrNotFound {
		return nil
	}
	return err
}
